package com.work.work.util;

        import com.fasterxml.jackson.databind.ObjectMapper;
        import com.work.work.common.R;
        import com.work.work.common.RequiresRoles;
        import com.work.work.util.JwtUtil;
        import io.jsonwebtoken.Claims;
        import io.jsonwebtoken.JwtException;
        import jakarta.servlet.http.HttpServletRequest;
        import jakarta.servlet.http.HttpServletResponse;
        import lombok.extern.slf4j.Slf4j;
        import org.springframework.beans.factory.annotation.Autowired;
        import org.springframework.http.HttpMethod;
        import org.springframework.http.MediaType;
        import org.springframework.stereotype.Component;
        import org.springframework.web.method.HandlerMethod;
        import org.springframework.web.servlet.HandlerInterceptor;

        import java.io.IOException;
        import java.lang.reflect.Method;
        import java.util.Arrays;

        @Slf4j
        @Component
        public class AuthorizationInterceptor implements HandlerInterceptor {

            @Autowired
            private JwtUtil jwtUtil;

            @Autowired
            private ObjectMapper objectMapper;

            @Override
            public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
                // 获取请求方法
                String requestMethod = request.getMethod();

                // 如果是OPTIONS请求，直接放行
                if (HttpMethod.OPTIONS.matches(requestMethod)) {
                    response.setStatus(HttpServletResponse.SC_OK);
                    return true;
                }

                // 如果不是映射到方法，直接通过
                if (!(handler instanceof HandlerMethod)) {
                    return true;
                }

                // 获取处理方法
                HandlerMethod handlerMethod = (HandlerMethod) handler;
                Method method = handlerMethod.getMethod();

                // 获取RequiresRoles注解
                RequiresRoles requiresRoles = method.getAnnotation(RequiresRoles.class);
                if (requiresRoles == null) {
                    return true;
                }

                // 获取token
                String token = extractToken(request);
                if (token == null) {
                    handleError(response, HttpServletResponse.SC_UNAUTHORIZED, "未提供token或token格式错误");
                    return false;
                }

                try {
                    // 验证token
                    if (!jwtUtil.validateToken(token)) {
                        handleError(response, HttpServletResponse.SC_UNAUTHORIZED, "token已过期或无效");
                        return false;
                    }

                    // 解析token获取claims
                    Claims claims = jwtUtil.parseToken(token);

                    // 获取角色ID
                    Integer roleId = claims.get("roleId", Integer.class);
                    if (roleId == null) {
                        handleError(response, HttpServletResponse.SC_FORBIDDEN, "token中未包含角色信息");
                        return false;
                    }

                    // 验证角色权限
                    int[] allowedRoles = requiresRoles.value();
                    if (Arrays.stream(allowedRoles).noneMatch(role -> role == roleId)) {
                        handleError(response, HttpServletResponse.SC_FORBIDDEN, "无访问权限");
                        return false;
                    }

                    // 存储用户信息到请求属性中
                    request.setAttribute("userId", claims.get("userId", Integer.class));
                    request.setAttribute("username", claims.get("username", String.class));
                    request.setAttribute("roleId", roleId);

                    return true;
                } catch (JwtException e) {
                    log.error("Token验证失败", e);
                    handleError(response, HttpServletResponse.SC_UNAUTHORIZED, "token验证失败");
                    return false;
                } catch (Exception e) {
                    log.error("权限验证错误", e);
                    handleError(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "服务器内部错误");
                    return false;
                }
            }

            private String extractToken(HttpServletRequest request) {
                String bearerToken = request.getHeader("Authorization");
                if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
                    return bearerToken.substring(7);
                }
                return null;
            }

            private void handleError(HttpServletResponse response, int status, String message) throws IOException {
                response.setStatus(status);
                response.setContentType(MediaType.APPLICATION_JSON_VALUE);
                response.setCharacterEncoding("UTF-8");
                response.getWriter().write(objectMapper.writeValueAsString(R.fail(message)));
            }
        }